<template>
  <div class="city-list">
    <a @click="selectProvice()">全部</a>
    <a @click="selectProvice('上海')">上海</a>
    <a @click="selectProvice('北京')">北京</a>
    <a @click="selectProvice('深圳')">深圳</a>
    <a @click="selectProvice('成都')">成都</a>
    <a @click="selectProvice('武汉')">武汉</a>
    <a @click="gepo">获取位置</a>
  </div>
  <div id="container"></div>
  <MessageCard :hidden="showBox" @close="closeBox" :title="cityData?.name">
    <p>人口：{{ cityData?.value }}</p>
    <p>生产总值：{{ cityData?.value2 }}</p>
  </MessageCard>
</template>
<script setup lang="ts">
import * as THREE from 'three';
import { onMounted, ref } from 'vue';
import CreateBar from './CreateBar';
import CreateThree from '@/three/base';
import Create3DMark from '@/three/3DMark';
import Create3DChina from '@/three/3DChina';
import CamerAnimet from '@/three/CamerAnimet';
import MessageCard from '@/components/MessageCard.vue';
const cityData = ref({ name: '', value: '', value2: '' });
const showBox = ref(false);
const closeBox = () => {
  showBox.value = false;
};
const scene = new CreateThree({
  stats: true,
  css2D: true,
  background: new THREE.Color('#e7eef7'),
  fog: new THREE.Fog('#e7eef7', 400, 1000),
  camera: {
    position: { y: 1000 }
  },
  control: {
    minDistance: 10,
    maxDistance: 5000,
    enableDamping: true,
    maxPolarAngle: Math.PI / 2.5
  },
  renderer: {
    antialias: true
  }
});
const textureLoader = new THREE.TextureLoader();
const chinaMap = new Create3DChina({
  url: 'data/china.json',
  map: 'images/china.jpg',
  normal: {
    scale: new THREE.Vector2(1, 1),
    map: 'images/districtTexture.jpg'
  }
});
const bars = new CreateBar('data/china_city_gdp.json');
const cityMarks = new Create3DMark('data/china_city_gdp.json');
const camerAnimet = new CamerAnimet(scene.camera, scene.control);
const createLight = () => {
  // 环境光
  scene.add(new THREE.AmbientLight(0xffffff, 2));
  // 设置光源位置
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(0, 100, 0);
  scene.add(light);
};

const selectProvice = (name = '') => {
  const data = {
    camera: [22.56, 301.65, 54.13],
    target: [9.56, -13.35, -18.87]
  };
  const itemData = cityMarks.getData(name);
  camerAnimet.move(
    itemData || data,
    () => {
      if (!name || name !== cityData.value?.name) {
        showBox.value = false;
      }
    },
    () => {
      cityMarks.show(name);
      if (name) {
        showBox.value = true;
        cityData.value = itemData;
      }
    }
  );
};
const createWorldPlan = box => {
  const width = 3 * (box.max.x - box.min.x);
  const map = textureLoader.load('images/world-plan-2.jpg');
  map.colorSpace = THREE.SRGBColorSpace;
  const mesh = new THREE.Mesh(
    new THREE.PlaneGeometry(width, width),
    new THREE.MeshPhysicalMaterial({ map, side: THREE.DoubleSide })
  );
  mesh.name = '背景';
  return mesh;
};
const createMap = async () => {
  await cityMarks.load();
  await chinaMap.load();
  const group = new THREE.Group();
  chinaMap.add(cityMarks.group);
  chinaMap.add(bars.mesh);
  group.add(chinaMap.group);
  const plan = createWorldPlan(chinaMap.box);
  group.add(plan);
  scene.add(group);
  chinaMap.move(-579.5, -186);
  group.rotateX(-Math.PI * 0.5);
};
const raycaster = new THREE.Raycaster();
onMounted(async () => {
  scene.bind('#container');
  render();
  createLight();
  await createMap();
  selectProvice();
  let hoverItem;
  window.addEventListener('mousemove', e => {
    const { clientX, clientY } = e;
    const mouse = new THREE.Vector2(0, 0);
    mouse.x = (clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, scene.camera);
    const body2 = scene.scene.getObjectByName('body2');
    if (body2 && body2.children.length) {
      const intersects = raycaster.intersectObjects(body2.children, true);
      if (hoverItem) {
        hoverItem.material.opacity = 0;
        hoverItem = null;
      }
      if (intersects.length) {
        intersects[0].object.material.opacity = 0.2;
        hoverItem = intersects[0].object;
      }
    }
  });
});
const render = (time?) => {
  scene.update(time);
  cityMarks.update(time);
  camerAnimet.update(time);
  bars.update(scene.camera);
  requestAnimationFrame(render);
};
</script>
<style lang="less" scoped>
.city-list {
  position: fixed;
  right: 10px;
  bottom: 10px;
  color: #fff;
  text-align: center;
  z-index: 2;

  a {
    margin: 5px;
    line-height: 1;
    display: block;
    cursor: pointer;
    background: #000;
    padding: 10px 20px;
  }
}
</style>
